package com.example.mykotlin.controller

import cn.dev33.satoken.annotation.SaCheckPermission
import com.example.mykotlin.base.result.PageParam
import com.example.mykotlin.base.result.ServiceException
import com.example.mykotlin.base.util.Audit
import com.example.mykotlin.base.util.runService
import com.example.mykotlin.base.util.selectById
import com.example.mykotlin.base.util.tryOnly
import com.example.mykotlin.mapper.RolePermissionMapper
import com.example.mykotlin.model.dto.InsertPermissionRolesDTO
import com.example.mykotlin.model.entity.ApiPermission
import com.example.mykotlin.model.entity.Role
import com.example.mykotlin.model.entity.RolePermission
import com.example.mykotlin.model.enums.SystemRole
import com.mybatisflex.kotlin.extensions.condition.allAnd
import com.mybatisflex.kotlin.extensions.db.deleteWith
import com.mybatisflex.kotlin.extensions.db.filter
import com.mybatisflex.kotlin.extensions.db.mapper
import com.mybatisflex.kotlin.extensions.db.paginate
import com.mybatisflex.kotlin.extensions.kproperty.eq
import com.mybatisflex.kotlin.extensions.kproperty.`in`
import com.mybatisflex.kotlin.extensions.wrapper.andAll
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import jakarta.validation.constraints.NotEmpty
import org.apache.commons.lang3.StringUtils
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController

@Tag(name = "接口权限资源表Controller", description = "相关接口")
@RestController
@Validated
@RequestMapping("/apiPermission")
class ApiPermissionController {
    @GetMapping
    @Operation(summary = "根据主键查询接口权限资源", description = "返回接口权限资源ApiPermission对象")
    @SaCheckPermission("GET_apiPermission")
    fun getApiPermissionById(@RequestParam @NotEmpty(message = "主键不能为空") id: String) =
        runService { selectById<ApiPermission>(id) }

    @GetMapping("/inPage")
    @Operation(summary = "分页条件查询接口权限资源", description = "返回接口权限资源ApiPermission对象列表")
    @SaCheckPermission("GET_apiPermission_inPage")
    fun getApiPermissionInPage(apiPermission: ApiPermission, @Validated p: PageParam) = runService {
        paginate<ApiPermission>(p.page()) {
            andAll(
                (ApiPermission::id eq apiPermission.id).`when`(StringUtils.isNotEmpty(apiPermission.id)),
                (ApiPermission::name eq apiPermission.name).`when`(StringUtils.isNotEmpty(apiPermission.name)),
                (ApiPermission::uriPath eq apiPermission.uriPath).`when`(StringUtils.isNotEmpty(apiPermission.uriPath)),
                (ApiPermission::method eq apiPermission.method).`when`(StringUtils.isNotEmpty(apiPermission.method)),
                (ApiPermission::description eq apiPermission.description).`when`(StringUtils.isNotEmpty(apiPermission.description)),
            )
        }
    }

    @PostMapping("/role")
    @Operation(summary = "权限分配给多个角色", description = "权限分配给多个角色")
    @SaCheckPermission("POST_permission_role")
    @Audit
    fun insertPermissionRoles(@RequestBody permissionRoles: InsertPermissionRolesDTO) = runService {
        selectById<ApiPermission>(permissionRoles.permissionId!!)
            ?: throw ServiceException("[permissionId=${permissionRoles.permissionId}]数据不存在")
        if (!permissionRoles.addRoleList.isNullOrEmpty()) {
            val addRoleSet = permissionRoles.addRoleList!!.toHashSet()
            addRoleSet.remove(SystemRole.SUPER_ADMIN.name)
            if (addRoleSet.isNotEmpty()) {
                val validRoleList = filter<Role>(Role::id) { Role::id `in` addRoleSet }
                if (validRoleList.isNotEmpty()) {
                    val validRoleIdList = validRoleList.map { it.id ?: "" }
                    val hasExistList = filter<RolePermission> {
                        allAnd(
                            RolePermission::permissionId eq permissionRoles.permissionId,
                            RolePermission::roleId `in` validRoleIdList
                        )
                    }
                    if (hasExistList.isEmpty()) {
                        tryOnly {
                            mapper<RolePermissionMapper>().insertBatch(validRoleIdList.map {
                                RolePermission(it, permissionRoles.permissionId)
                            })
                        }

                    } else if (hasExistList.size < validRoleIdList.size) {
                        tryOnly {
                            val minus = validRoleIdList.minus(hasExistList.map { it.roleId }.toSet())
                            mapper<RolePermissionMapper>().insertBatch(minus.map {
                                RolePermission(it, permissionRoles.permissionId)
                            })
                        }
                    }
                }
            }
        }
        if (!permissionRoles.removeRoleList.isNullOrEmpty()) {
            tryOnly {
                deleteWith<RolePermission> {
                    allAnd(
                        RolePermission::permissionId eq permissionRoles.permissionId,
                        RolePermission::roleId `in` permissionRoles.removeRoleList!!
                    )
                }
            }
        }
        return@runService true
    }


}